home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / text / misc / mpage.lha / mpage / post.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-07-25  |  22.6 KB  |  801 lines

  1. /*
  2.  * post.c
  3.  */
  4.  
  5. /*
  6.  * mpage:    a program to reduce pages of print so that several pages
  7.  *           of output appear on one printed page.
  8.  *
  9.  * Written by:
  10.  *   ...!uunet!\                       Mark Hahn, Sr Systems Engineer
  11.  *              >pyrdc!mark            Pyramid Technology Corporation
  12.  * ...!pyramid!/                       Vienna, Va    (703)848-2050
  13.  *
  14.  *
  15.  * Copyright (c) 1988 Mark P. Hahn, Herndon, Virginia
  16.  * Copyright (c) 1994-1997 Marcel J.E. Mol, The Netherlands
  17.  *                    marcel@mesa.nl
  18.  *  
  19.  *     Permission is granted to anyone to make or distribute verbatim
  20.  *     copies of this document as received, in any medium, provided
  21.  *     that this copyright notice is preserved, and that the
  22.  *     distributor grants the recipient permission for further
  23.  *     redistribution as permitted by this notice.
  24.  *
  25.  */
  26.  
  27.  
  28. #include "mpage.h"
  29. #include <string.h>
  30.  
  31.  
  32. /*
  33.  * character spaces used throughout for holding the current line from
  34.  * the input file
  35.  */
  36. static char currline[LINESIZE];
  37. static char *file_name;
  38.  
  39. /*
  40.  * for ps documents, used to remember if we have come across the
  41.  * tailer section.  reset at the beginning of processing for each file
  42.  */
  43. static int ps_at_trailer;
  44.  
  45. /*
  46.  * this is the type of postscript document we are processing
  47.  */
  48. static int ps_posttype;
  49.  
  50. /*
  51.  * set to one if we have a inputline that must be preceded by something...
  52.  * used for dvips output without PS comments.
  53.  */
  54. static int have_line = 0;
  55.  
  56. /*
  57.  * number of output lines on current logical page
  58.  */
  59. static plcnt;
  60.  
  61.  
  62. int have_showsheet = 0;
  63.  
  64. char ps_roff_xi [16]; /* to hold the DITROFF xi line... */
  65.  
  66. static char * tex1;   /* to capture important dvi2ps lines... */
  67. static char * tex2;
  68.  
  69. /*
  70.  * Function declarations 
  71.  */
  72. static int   ps_gettype();
  73. static void  do_post_doc();
  74. #if 0
  75. static void  do_other_doc();
  76. #endif
  77. static void  ps_copyprolog();
  78. static void  ps_roff_copyprolog();
  79. static void  ps_mpage_copyprolog();
  80. static void  ps_skip_to_page();
  81. static int   do_post_sheet();
  82. static void  ps_sheetsetup();
  83. static int   post_onepage();
  84. static void  do_roff_tailer();
  85. int   ps_check();
  86. void  do_ps_doc();
  87.  
  88. /*
  89.  * Peek at the first two chacters on the open file and check for the
  90.  * two character postscript flag "%!".  If the file is not postscript
  91.  * then the characters are pushed back into the input stream (hopefully).
  92.  */
  93. int
  94. ps_check(infd)
  95.  FILE *infd;
  96. {
  97.     int firstchar;
  98.     int secondchar;
  99.     
  100.     Debug(DB_PSCHECK, "%%ps_check: in ps_check\n", 0);
  101.  
  102.     /*
  103.      * eliminate blank files
  104.      */
  105.     if ((firstchar = fgetc(infd)) == EOF) {
  106.         Debug(DB_PSCHECK, "%%ps_check: file is blank\n", 0);
  107.         return 0;
  108.     }
  109.  
  110.     /*
  111.      * Skip any CTRL-D chars
  112.      * Hope there are no text files starting with ctrl-d's
  113.      */
  114.     while (firstchar == 4)
  115.         firstchar = fgetc(infd);
  116.  
  117.     /*
  118.      * eliminate non-postscript files
  119.      */
  120.     if (firstchar != '%') {
  121.         Debug(DB_PSCHECK, "%ps_check: 1st char is '%c' not '%'\n", firstchar);
  122.         if (ungetc(firstchar, infd) == EOF) {
  123.             fprintf(stderr, "%s: Lost first character of file ", MPAGE);
  124.             fprintf(stderr, "while checking for postscript\n.");
  125.         }
  126.         return 0;
  127.     }
  128.     Debug(DB_PSCHECK, "%%ps_check: 1st char is '%c'\n", firstchar);
  129.     /*
  130.      * eliminate one character files (containing only a %)
  131.      */
  132.     if ((secondchar = fgetc(infd)) == EOF) {
  133.         Debug(DB_PSCHECK, "%%ps_check: no second char\n", 0);
  134.         if (ungetc(firstchar, infd) == EOF) {
  135.             fprintf(stderr, "%s: Lost first character of file ", MPAGE);
  136.             fprintf(stderr, "while checking for postscript\n.");
  137.         }
  138.         return 0;
  139.     }
  140.     /*
  141.      * eliminate files that don't have the full two character
  142.      * sequence of "%!".
  143.      */
  144.     if (secondchar != '!') {
  145.         Debug(DB_PSCHECK, "%%ps_check: 2nd char is '%c' not '!'\n", secondchar);
  146.         if (ungetc(secondchar, infd) == EOF) {
  147.             fprintf(stderr, "%s: Lost first two characters of ", MPAGE);
  148.             fprintf(stderr, "file while checking for postscript\n.");
  149.             return 0;
  150.         }
  151.         if (ungetc(firstchar, infd) == EOF) {
  152.             fprintf(stderr, "%s: Lost first character of file ", MPAGE);
  153.             fprintf(stderr, "while checking for postscript.\n");
  154.         }
  155.         return 0;
  156.     }
  157.     /*
  158.      * for post script files the first two characters (the "%!") are
  159.      * digested by this routine.  It's just easier than dealing
  160.      * with the problems encounted if the characters can't be ungetc'ed.
  161.      */
  162.     Debug(DB_PSCHECK, "%%ps_check: 2nd char is '%c'\n", secondchar);
  163.     Debug(DB_PSCHECK, "%%ps_check: input is postscript\n", 0);
  164.  
  165.     return 1;
  166.  
  167. } /* ps_check */
  168.  
  169.  
  170.  
  171. static int
  172. ps_gettype(fd, outfd)
  173.  FILE *fd;
  174.  FILE *outfd;
  175. {
  176.     int ps_type, end_comments;
  177.  
  178.     Debug(DB_PSDOC, "%%ps_gettype: in ps_gettype\n", 0);
  179.     /*
  180.      * error check for truncated files
  181.      */
  182.     if (fgets(currline, LINESIZE-1, fd) == NULL) {
  183.         Debug(DB_PSDOC, "%%ps_gettype: got eof on first line\n", 0);
  184.         return PS_NONE;
  185.     }
  186.     /*
  187.      * check for non-conforming postscript
  188.      * Note that %! is already gone down the drain...
  189.      */
  190.     if (strncmp(currline, PS_FLAG, strlen(PS_FLAG)) != 0) {
  191.         Debug(DB_PSDOC, "%%ps_gettype: no match PS_FLAG \"%s\"\n", currline);
  192.         return PS_OTHER;
  193.     }
  194.     /*
  195.      * we have some form of conforming postscript, try to identify the
  196.      * type
  197.      */
  198.     Debug(DB_PSDOC, "%%ps_gettype: conforming postscript\n", 0);
  199.     end_comments = 0;
  200.     ps_type = PS_CONFORM;
  201.     while (!end_comments) {
  202.         /*
  203.          * if we get end of file then we assume non-conforming PS
  204.          */
  205.         if (fgets(currline, LINESIZE-1, fd) == NULL) {
  206.             Debug(DB_PSDOC, "%%ps_gettype: eof in comments\n", 0);
  207.             return PS_OTHER;
  208.         }
  209.         /*
  210.          * if we have run out of leading comments then assume 
  211.          * conforming PS (because we had a valid "%!" line)
  212.          */
  213.         if (currline[0] != '%') {
  214.             Debug(DB_PSDOC, "%%ps_gettype: out off comments\n", 0);
  215.             fprintf(outfd, "%s", currline);
  216.             return PS_CONFORM;
  217.         }
  218.         /*
  219.          * print out the comment line with an extra % to disguise the comment
  220.          */
  221.         fprintf(outfd, "%%%s", currline);
  222.         /*
  223.          * check for the end of the leading comments section
  224.          */
  225.         if (strncmp(currline, "%%EndComments", 13) == 0)
  226.             end_comments = 1;
  227.         /*
  228.          * Some tricky way to handle MS-windows postscript files...
  229.          * probably doesn't work.
  230.         */
  231.         if (strncmp(currline, "%%Pages:", 8) == 0 &&
  232.             ps_type == PS_MSWINDOWS)
  233.             return ps_type;
  234.         /*
  235.          * once we know the type of PS, we no longer need to keep
  236.          * checking.
  237.          */
  238.         if (ps_type != PS_CONFORM)
  239.             continue;
  240.         /*
  241.          * check for mpage output
  242.          */
  243.         if (!strncmp(currline, "%%Creator: ", 11)) {
  244.             if (!strncmp(currline+11, MPAGE, strlen(MPAGE))) {
  245.                 Debug(DB_PSDOC, "%%ps_gettype: mpage document\n", 0);
  246.                 ps_type = PS_MPAGE;
  247.             }
  248.             else if (!strncmp(currline+11, "Windows PSCRIPT", 15)) {
  249.                 Debug(DB_PSDOC, "%%ps_gettype: windows document\n", 0);
  250.                 ps_type = PS_MSWINDOWS;
  251.             }
  252.             else if (!strncmp(currline+11, "dvips", 5)) {
  253.                 Debug(DB_PSDOC, "%%ps_gettype: idvips\n", 0);
  254.                 ps_type = PS_TEX;
  255.             }
  256.         }
  257.         /*
  258.          * check for psroff/tex output
  259.          */
  260.         if (strncmp(currline, "%%Title: ", 9) == 0) {
  261.             if (strstr(currline, "ditroff")) {
  262.                 Debug(DB_PSDOC, "%%ps_gettype: psroff\n", 0);
  263.                 ps_type = PS_PSROFF;
  264.             }
  265.             else if (strstr(currline, ".dvi")) {
  266.                 Debug(DB_PSDOC, "%%ps_gettype: dvi2ps\n", 0);
  267.                 ps_type = PS_TEX;
  268.             }
  269.         }
  270.         if (strncmp(currline, "%DVIPS", 6) == 0) {
  271.             Debug(DB_PSDOC, "%%ps_gettype: dvips\n", 0);
  272.             if (ps_type != PS_TEX)
  273.                 ps_type = PS_TEX2;
  274.             return ps_type; 
  275.         }
  276.     }
  277. #ifdef DEBUG
  278.     if (ps_type == PS_CONFORM) {
  279.         Debug(DB_PSDOC, "%%ps_gettype: unknown type, conforming PS\n", 0);
  280.     }
  281. #endif
  282.  
  283.     return ps_type;
  284.  
  285. } /* ps_gettype */
  286.  
  287.  
  288.  
  289. void
  290. do_ps_doc(fd, asheet, outfd, fname)
  291.  FILE *fd;
  292.  struct sheet *asheet;
  293.  FILE *outfd;
  294.  char * fname;
  295. {
  296.  
  297.     Debug(DB_PSDOC, "%%do_ps_doc: postscript document\n", 0);
  298.  
  299.     file_name = fname;
  300.     ps_posttype = ps_gettype(fd,outfd);
  301.     Debug(DB_PSDOC, "%%do_ps_doc: document type is %d\n", ps_posttype);
  302.     if (ps_posttype != PS_NONE)
  303.         do_post_doc(fd, asheet, outfd);
  304.  
  305.     return;
  306.  
  307. } /* do_ps_doc */
  308.  
  309.  
  310.  
  311. static void
  312. do_post_doc(fd, asheet, outfd)
  313.  FILE *fd;
  314.  struct sheet *asheet;
  315.  FILE *outfd;
  316. {
  317.  
  318.     ps_at_trailer = FALSE;
  319.     Debug(DB_POST, "%%do_post_doc: prolog\n", 0);
  320.     ps_copyprolog(fd, outfd);
  321.     /*
  322.      * while there is still input, print pages
  323.      */
  324.     Debug(DB_POST, "%%do_post_doc: pages\n", 0);
  325.     do_sheets(do_post_sheet, fd, asheet, outfd);
  326.     Debug(DB_POST, "%%do_post_doc: trailer\n", 0);
  327.     do_roff_tailer(fd, outfd);
  328.  
  329.     return;
  330.  
  331. } /* do_post_doc */
  332.  
  333.  
  334. #if 0
  335. /* not used yet... */
  336. static void
  337. do_other_doc(fd, asheet, outfd)
  338.  FILE *fd;
  339.  struct sheet *asheet;
  340.  FILE *outfd;
  341. {
  342.  
  343.     ps_at_trailer = FALSE;
  344.     ps_copyprolog(fd, outfd);
  345.  
  346.     return;
  347.  
  348. } /* do_other_doc */
  349. #endif
  350.  
  351.  
  352.  
  353. static void
  354. ps_copyprolog(fd, outfd)
  355.  FILE *fd;
  356.  FILE *outfd;
  357. {
  358.  
  359.     Debug(DB_PSDOC, "%%ps_copyprolog: adding mpage prolog\n", 0);
  360.     if (!have_showsheet) {
  361.         fprintf(outfd, "/showsheet { showpage } bind def\n");
  362.         fprintf(outfd, "/showpage { } def\n");
  363.         have_showsheet = 1;
  364.     }
  365.     had_ps = 1;
  366.     Debug(DB_PSDOC, "%%ps_copyprolog: copying prolog\n", 0);
  367.     if (ps_posttype == PS_PSROFF) {
  368.         Debug(DB_PSDOC, "%%ps_copyprolog: calling ps_roff_copyprolog\n",0);
  369.         ps_roff_copyprolog(fd, outfd);
  370.         return;
  371.     }
  372.     if (ps_posttype == PS_MPAGE) {
  373.         Debug(DB_PSDOC, "%%ps_copyprolog: calling ps_mpage_copyprolog\n",0);
  374.         ps_mpage_copyprolog(fd, outfd);
  375.         return;
  376.     }
  377.     while (fgets(currline, LINESIZE-1, fd) != NULL) {
  378.         if (strncmp(currline, "%%Page:", 7) == 0) {
  379.             fprintf(outfd, "%% %s", currline);
  380.             return;
  381.         }
  382.         if (ps_posttype == PS_TEX || ps_posttype == PS_TEX2) { 
  383.             if (ps_posttype == PS_TEX2 && strstr(currline, " bop ")) {
  384.                 /* dvips output without comments... */
  385.                 have_line = 1;
  386.                 return;
  387.             }
  388.             if (strncmp(currline, "TeXDict", 7) == 0) {
  389.                 /*
  390.                  * Hope all dvi2ps progs work the same:
  391.                  * capture the TeX init code so we can run it 'manually' for
  392.                  * every page. This is needed as this code sets up a gstate 
  393.                  * that conflicts with mpage...
  394.                  * This trick seems to work for text, but figures within the dvi
  395.                  * file seem to have a mind of their own...
  396.                  */
  397.                 if (tex1)
  398.                     free(tex1);
  399.                 tex1 = malloc(strlen(currline)+1);
  400.                 strcpy(tex1, currline);
  401.                 fprintf(outfd, "%s", currline);
  402.  
  403.                 fgets(currline, LINESIZE-1, fd);
  404.                 if (tex2)
  405.                     free(tex2);
  406.                 tex2 = malloc(strlen(currline)+1);
  407.                 strcpy(tex2, currline);
  408.             }
  409.         }
  410.         fprintf(outfd, "%s", currline);
  411.     }
  412.     Debug(DB_PSDOC, "%%ps_copyprolog: eof before %%%%EndProlog\n", 0);
  413.     fprintf(outfd, "%%%%EndProlog\n");
  414.  
  415.     return;
  416.  
  417. } /* ps_copyprolog */
  418.  
  419.  
  420.  
  421. static void
  422. ps_roff_copyprolog(fd, outfd)
  423.  FILE *fd;
  424.  FILE *outfd;
  425. {
  426.  
  427.     Debug(DB_PSDOC, "%%ps_roff_copyprolog: copying psroff prolog\n", 0);
  428.     while(fgets(currline, LINESIZE-1, fd) != NULL) {
  429.  /*       if (strcmp(currline, "xi\n") == 0) */
  430.         if (strstr(currline, "xi\n")) {
  431.             fprintf(outfd, "%%%s", currline); 
  432.             strcpy(ps_roff_xi, currline);
  433.         }
  434.         else if (strncmp(currline, "%%Page:", 7) == 0) {
  435.             fprintf(outfd, "/p { } def\n");
  436.             fprintf(outfd, "/xt { } def\n");
  437.             fprintf(outfd, "/xs { } def\n");
  438.             fprintf(outfd, "%% %s", currline);
  439.             Debug(DB_PSDOC, "%%ps_copyprolog: Done\n", 0);
  440.             return;
  441.         }
  442.         else
  443.             fprintf(outfd, "%s", currline);
  444.     }
  445.     Debug(DB_PSDOC, "%%ps_copyprolog: eof before %%%%EndProlog\n", 0);
  446.     fprintf(outfd, "/p { } def\n");
  447.     fprintf(outfd, "/xt { } def\n");
  448.     fprintf(outfd, "/xs { } def\n");
  449.     fprintf(outfd, "%%%%EndProlog\n");
  450.  
  451.     return;
  452.  
  453. } /* ps_roff_copyprolog */
  454.  
  455.  
  456.  
  457. static void
  458. ps_mpage_copyprolog(fd, outfd)
  459.  FILE *fd;
  460.  FILE *outfd;
  461. {
  462.  
  463.     Debug(DB_PSDOC, "%%ps_mpage_copyprolog: skipping mpage prolog\n", 0);
  464.     while(fgets(currline, LINESIZE-1, fd) != NULL) {
  465.         if (strncmp(currline, "%%Page:", 7) == 0)  {
  466.             fprintf(outfd, "%% %s", currline);
  467.             Debug(DB_PSDOC, "%%ps_copyprolog: Done\n", 0);
  468.             return;
  469.         }
  470.     }
  471. } /* ps_mpage_copyprolog */
  472.  
  473.  
  474.  
  475. static void
  476. ps_skip_to_page(fd)
  477.  FILE *fd;
  478. {
  479.  
  480.     Debug(DB_PSDOC, "%%ps_skip to page: reading until %%%%Page:\n", 0);
  481.     while(fgets(currline, LINESIZE-1, fd) != NULL) {
  482.         Debug(DB_PSDOC, "%% %s", currline);
  483.         if (strncmp(currline, "%%Page:", 7) == 0)
  484.             return;
  485.     }
  486.     Debug(DB_PSDOC, "%%ps_skip_to_page: eof before %%%%Page:\n", 0);
  487.  
  488.     return;
  489.  
  490. } /* ps_skip_to_page */
  491.  
  492. /* GPN */
  493. /* #define NSCALE    to take care of previous scaling */
  494. #ifdef NSCALE
  495. char *NScale =  "/gpnsavematrix {orgmatrix currentmatrix pop} bind def\n"
  496.                 "/gpnrestorematrix {orgmatrix setmatrix} bind def\n"
  497.                 "/orgmatrix matrix def\n"
  498.                 "gpnsavematrix\n"
  499.                 "orgmatrix orgmatrix invertmatrix pop\n"
  500.                 "/gpnxs\n"
  501.                 "    orgmatrix 0 get 0.0000 eq\n"
  502.                 "     {orgmatrix 1 get abs}\n"
  503.                 "     {orgmatrix 0 get abs}\n"
  504.                 "    ifelse def\n"
  505.                 "/gpnys\n"
  506.                 "    orgmatrix 3 get 0.0000 eq\n"
  507.                 "     {orgmatrix 2 get abs}\n"
  508.                 "     {orgmatrix 3 get abs}\n"
  509.                 "    ifelse def\n"
  510.                 "/gpnxs gpnxs gscurrentresolution 0 get 72 div mul def\n"
  511.                 "/gpnys gpnys gscurrentresolution 1 get 72 div mul def\n";
  512. #endif /* NSCALE */
  513.  
  514. static int
  515. do_post_sheet(fd, asheet, outfd)
  516.  FILE *fd;
  517.  struct sheet *asheet;
  518.  FILE *outfd;
  519. {
  520.     int rtn_val = FILE_MORE;
  521.     int sh_high, sh_wide;
  522.  
  523.     if ((points->pp_origin_x == 0 && !points->skip) || opt_file) {
  524.         /*
  525.          * keep track of the pages printed
  526.          */
  527.         ps_pagenum++;
  528.         fprintf(outfd, "%%%%Page: %d %d\n", ps_pagenum, ps_pagenum);
  529. # ifdef DEBUG
  530.         if (Debug_flag & DB_PSMPAGE)
  531.             fprintf(outfd, "(Page: %d\\n) print flush\n", ps_pagenum);
  532. # endif /* DEBUG */
  533.  
  534.         /*
  535.          * Now is the time to print a sheet header...
  536.          * for now, this has to be done before outline...
  537.          */
  538.         sheetheader(outfd, file_name);
  539.  
  540.         /*
  541.          * print the page outline
  542.          */
  543.         mp_outline(outfd, asheet);
  544.  
  545.         /*
  546.          * run through the list of base points for putting reduced pages
  547.          * on the printed page
  548.          */
  549.         points = asheet->sh_pagepoints;
  550.     }
  551.     /*while (points->pp_origin_x != 0 && rtn_val == FILE_MORE) {*/
  552.     while ((points->pp_origin_x!=0 || points->skip) && rtn_val == FILE_MORE) {
  553.  
  554.         /* GPN. skip this page ?*/
  555.           if (points->skip!=0)   {
  556.              ps_skip_to_page(fd);
  557.              points++;
  558.              continue;
  559.           }
  560.  
  561.         /*
  562.          * print one reduced page by moveing to the proper point,
  563.          * turning to the proper aspect, scaling to the proper
  564.          * size, and setting up a clip path to prevent overwritting;
  565.          * the print a reduced page of output
  566.          */
  567.         Debug(DB_PSMPAGE, "%%%% %%%%ReducedPageStartsHere\n", outfd);
  568.         fprintf(outfd, "/sheetsave save def\n");
  569.         fprintf(outfd, "gsave\n");
  570. # ifdef DEBUG
  571.         if (Debug_flag & DB_PSMPAGE) {
  572.             fprintf(outfd, "(    %d %d translate %d rotate\\n)",
  573.                             points->pp_origin_x(), points->pp_origin_y(),
  574.                             asheet->sh_rotate);
  575.             fprintf(outfd, " print flush\n");
  576.         }
  577. # endif /* DEBUG */
  578.  
  579. #ifdef  NSCALE /*GPN*/
  580.         fprintf (outfd, NScale);
  581.         fprintf(outfd, "%d gpnxs mul %d gpnxs mul translate %d rotate\n",
  582.                       points->pp_origin_x(), points->pp_origin_y(),
  583.                                                      asheet->sh_rotate);
  584.  
  585.         sh_wide = (*asheet->sh_width)();
  586.         sh_high = (*asheet->sh_height)();
  587. #else /* NSCALE */
  588.         fprintf(outfd, "%d %d translate\n",
  589.                        points->pp_origin_x(), points->pp_origin_y());
  590.        if (asheet->sh_rotate)
  591.             fprintf(outfd, "%d rotate\n", asheet->sh_rotate);
  592.  
  593.         /*
  594.          * Take extra page margins into account
  595.          */
  596.         sh_wide = (*asheet->sh_width)() - pagemargin_left - pagemargin_right;
  597.         sh_high = (*asheet->sh_height)() - pagemargin_top - pagemargin_bottom;
  598. #endif
  599.  
  600.         if (opt_square) {
  601.             int newhigh = sh_high, newwide = sh_wide;
  602.  
  603.             if (sh_wide * ps_height > sh_high * ps_width)
  604.                 newwide = (sh_high * ps_width) / ps_height;
  605.             else
  606.                 newhigh = (sh_wide * ps_height) / ps_width;
  607.  
  608. #ifdef  NSCALE /*GPN*/
  609.             fprintf(outfd, "%d gpnxs mul %d gpnys mul translate\n",
  610. #else
  611.             fprintf(outfd, "%d %d translate\n",
  612. #endif
  613.  
  614.                            (sh_wide - newwide) / 2, (sh_high - newhigh) / 2);
  615.             sh_wide = newwide;
  616.             sh_high = newhigh;
  617.        }
  618.  
  619. #ifndef NSCALE
  620.         fprintf(outfd, "%d %d translate\n", pagemargin_left, pagemargin_bottom);
  621. #endif
  622.  
  623.         fprintf(outfd, "%d %d div %d %d div scale\n",
  624.                        sh_wide, ps_width, sh_high, ps_height);
  625.         /* output the clip path */
  626.  
  627. #ifdef  NSCALE /*GPN*/
  628.         fprintf(outfd, "0 0 moveto 0 %d gpnys mul lineto %d gpnxs mul"
  629.                        " %d gpnys mul lineto ",
  630.                           ps_height, ps_width, ps_height);
  631.         fprintf(outfd, "%d gpnxs mul 0 lineto\n", ps_width);
  632. #else /* NSCALE */
  633.         fprintf(outfd, "0 0 moveto 0 %d lineto %d %d lineto ",
  634.                        ps_height, ps_width, ps_height);
  635.         fprintf(outfd, "%d 0 lineto\n", ps_width);
  636. #endif
  637.  
  638. #ifdef  NSCALE /*GPN*/
  639.        fprintf(outfd, "closepath clip\n");
  640. #else
  641.         fprintf(outfd, "closepath clip newpath\n");
  642. #endif /* NSCALE */
  643.         if ((ps_posttype == PS_TEX || ps_posttype == PS_TEX2) && tex1)
  644.             /* start dvi2ps init every page */
  645.         fprintf(outfd, "%s%s", tex1, tex2);
  646.  
  647.         /*
  648.          * do the individual sheet setup
  649.          */
  650.         ps_sheetsetup(outfd);
  651.         /*
  652.          * place one reduce page on the printed page
  653.          */
  654.         plcnt = 0;
  655.         rtn_val = post_onepage(fd, asheet, outfd);
  656.         /*
  657.          * clean up after mpage as drawn its page
  658.          */
  659.         fprintf(outfd, "grestore sheetsave restore\n");
  660.         points++;
  661.     }
  662.     /*
  663.      * print the sheet
  664.      */
  665.     if (points->pp_origin_x == 0 || (rtn_val == FILE_EOF && opt_file))
  666.         fprintf(outfd, "showsheet\n");
  667.  
  668.     /*
  669.      * let the upper level know about the status of possible EOF
  670.      */
  671.     return rtn_val;
  672.  
  673. } /* do_post_sheet */
  674.  
  675.  
  676.  
  677. static void
  678. ps_sheetsetup(outfd)
  679.  FILE *outfd;
  680. {
  681.  
  682.     switch (ps_posttype) {
  683.         case PS_PSROFF: fprintf(outfd, "%s", ps_roff_xi);
  684.                         fprintf(outfd, "/p {} def\n");
  685.                         break;
  686. /*
  687.         case PS_MPAGE:  fprintf(outfd, "/showpage {} def\n");
  688.                         break;
  689. */
  690.     }
  691.  
  692.         return;
  693.  
  694. } /* ps_sheetsetup */
  695.  
  696.  
  697.  
  698. static int
  699. post_onepage(fd, asheet, outfd)
  700.  FILE *fd;
  701.  struct sheet *asheet;
  702.  FILE *outfd;
  703. {
  704.  
  705.     Debug(DB_PSROFF, "%%post_onepage: Begin page\n", 0);
  706.     if (ps_at_trailer) {
  707.         Debug(DB_PSROFF, "%%post_onepage: still at trailer\n", 0);
  708.         return FILE_EOF;
  709.     }
  710.  
  711.     if (have_line) {
  712.         fprintf(outfd, "%s", currline);
  713.         have_line = 0;
  714.     }
  715.         
  716.     while(fgets(currline, LINESIZE-1, fd) != NULL) {
  717.         if (strncmp(currline, "%%Page:", 7) == 0) {
  718.             fprintf(outfd, "%% %s", currline);
  719.             /* only if there is already output to this logical page */
  720.             if (!plcnt)
  721.                 continue;
  722.             Debug(DB_PSROFF, "%%post_onepage: next page\n", 0);
  723.             return FILE_MORE;
  724.         }
  725.         if (strncmp(currline, "%%Trailer", 9) == 0) {
  726.             fprintf(outfd, "%% %s", currline);
  727.             Debug(DB_PSROFF, "%%post_onepage: found trailer\n", 0);
  728.             ps_at_trailer = TRUE;
  729.             return FILE_EOF;
  730.         }
  731.         /* For netscape output */
  732.         if (strncmp(currline, "%%EOF", 5) == 0) {
  733.             fprintf(outfd, "%% %s", currline);
  734.             Debug(DB_PSROFF, "%%post_onepage: EOF\n", 0);
  735.             return FILE_EOF;
  736.         }
  737.         if (ps_posttype == PS_MPAGE && strncmp(currline, "showsheet", 9) == 0)
  738.             continue;
  739.         if (ps_posttype == PS_TEX || ps_posttype == PS_TEX2) {
  740.             if (ps_posttype == PS_TEX2 &&
  741.                 (strstr(currline, "eop\n") || strstr(currline, "eop end\n"))) {
  742.                 fprintf(outfd, "%s", currline);
  743.                 Debug(DB_PSROFF, "%%post_onepage: found TEX eop\n", 0);
  744.                 return FILE_MORE;
  745.             }
  746.             if (strncmp(currline, "TeXDict", 7) == 0) {
  747.                 /*
  748.                  * Hope all dvi2ps progs work the same:
  749.                  * capture the TeX init code so we can run it 'manually' for
  750.                  * every page. This is needed as this code sets up a gstate 
  751.                  * that conflicts with mpage...
  752.                  * This trick seems to work for text, but figures within the dvi
  753.                  * file seem to have a mind of their own...
  754.                  */
  755.                 if (tex1)
  756.                     free(tex1);
  757.                 tex1 = malloc(strlen(currline)+1);
  758.                 strcpy(tex1, currline);
  759.                 fprintf(outfd, "%s", currline);
  760.  
  761.                 fgets(currline, LINESIZE-1, fd);
  762.                 if (tex2)
  763.                     free(tex2);
  764.                 tex2 = malloc(strlen(currline)+1);
  765.                 strcpy(tex2, currline);
  766.             }
  767.         }
  768.         fprintf(outfd, "%s", currline);
  769.         plcnt++;
  770.     }
  771.     Debug(DB_PSROFF, "%%post_onepage: eof\n", 0);
  772.  
  773.     return FILE_EOF;
  774.  
  775. } /* post_onepage */
  776.  
  777.  
  778.  
  779. static void
  780. do_roff_tailer(fd, outfd)
  781.  FILE *fd, *outfd;
  782. {
  783. #ifdef DEBUG
  784.         int i = 0;
  785. #endif
  786.  
  787.     Debug(DB_PSDOC, "%%do_roff_trailer: looking for eof\n", 0);
  788.     while(fgets(currline, LINESIZE-1, fd) != NULL) {
  789. #ifdef DEBUG
  790.         i++;
  791.         Debug(DB_PSDOC, "%%%s", currline);
  792. #endif
  793.         ;
  794.     }
  795.     Debug(DB_PSDOC, "%%do_roff_trailer: tailer of %d lines\n", i);
  796.  
  797.     return;
  798.  
  799. } /* do_roff_tailer */
  800.  
  801.